package com.emagic.manage.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.util.Log;

import com.emagic.manage.LifeApplication;
import com.xitaiinfo.library.utils.CommonUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * 图片处理工具
 * Created by Administrator on 2016/4/21.
 */
public class ImageUtils {
    private static final String TAG = ImageUtils.class.getSimpleName();


    /**
     * 按指定角度旋转bitmap
     *
     * @param angle  旋转角度
     * @param bitmap bitmap
     * @return Bitmap
     */
    public static Bitmap rotateBitmap(int angle, Bitmap bitmap) {
        Bitmap resizedBitmap = null;
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, true);

        return resizedBitmap;
    }

    /**
     * 获取指定路径的图像角度
     *
     * @param path
     */
    public static int readBitmapDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
        }
        return degree;
    }

    /**
     * 获取指定路径的图片高与宽
     * @param path
     * @return
     */
    public static String readBitmapSize(String path) {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, opts);

        int w = opts.outWidth;
        int h = opts.outHeight;

        StringBuilder sb = new StringBuilder();
        sb.append(w).append("*").append(h);

        return sb.toString();

    }

    /**
     * 图片解析参数值设定
     */
    private static BitmapFactory.Options bitmapManage(int inSampleSize) {

        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = false;
//        opts.inTempStorage = new byte[100 * 1024];
        opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
        opts.inSampleSize = inSampleSize;
        return opts;
    }


    /**
     * 保存图片
     *
     * @param degree
     * @param sPath
     * @param ww
     * @param hh
     * @return
     * @throws Exception
     */
    public static String saveBitmapByUri(int degree, String sPath, float ww, float hh) throws Exception {
        //图片压缩
        Bitmap bitmap = compressBitmap(sPath, ww, hh);
        //旋转度角
        bitmap = rotateBitmap(degree, bitmap);
        //生成缓存图片名称
        String photoName = CommonUtils.generateFileName(CommonUtils.FileType.FILE_TYPE_IMAGE);
        //获取缓存图片File对象
        File imageFile = CommonUtils.getAppCacheFile(photoName, LifeApplication.getInstance());

        if (imageFile == null) {
            throw new RuntimeException("photo cannot be created.");
        }
        //将压缩好的图片对象写入sdcard
        writeToSdcard(bitmap, imageFile);

        return imageFile.getAbsolutePath();
    }


    public static void saveBitmap(Bitmap src, File outFile, float ww, float hh) throws Exception{

        Bitmap newBitmap = compressBitmap(src, ww, hh);

        writeToSdcard(newBitmap, outFile);

//        NativeUtil.compressBitmap(newBitmap, outFile, true);
    }

    public static void saveBitmap(String src, File outFile ,float ww, float hh) {

        Bitmap newBitmap = compressBitmap(src, ww, hh);

        writeToSdcard(newBitmap, outFile);

//        NativeUtil.compressBitmap(newBitmap, outFile, true);
    }

    /**
     * 压缩图像
     *
     * @param src
     * @param ww
     * @param hh
     * @return
     * @throws Exception
     */
    public static Bitmap compressBitmap(Bitmap src, float ww, float hh) throws Exception {

        return compBitmapByScale(src, ww, hh);
    }

    /**
     * 压缩图像
     * 这里先缩放到指定的高宽，再进行图像质量上的压缩
     *
     * @param path
     * @param ww
     * @param hh
     * @return
     */
    public static Bitmap compressBitmap(String path, float ww, float hh) {

        //设置默认缩放的高宽
        if (ww <= 0 || hh <= 0) {
            ww = 480;
            hh = 800;
        }
        //按指定的高度及宽度缩小图片
        return compBitmapByScale(path, ww, hh);

        //按100KB的大小来压缩图像质量
//        bitmap = compBitmapByQuality(bitmap, 100);


//        return bitmap;
    }

    /**
     * 按比例压缩图片
     *
     * @param path
     * @param ww
     * @param hh
     * @return
     */
    public static Bitmap compBitmapByScale(String path, float ww, float hh) {

        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, opts);

        //获取源照片高度与宽度
        int w = opts.outWidth;
        int h = opts.outHeight;
        int be = 1;
        //缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        if (w >= h && w > ww) { //如果宽度大的话根据宽度固定大小缩放
            be = Math.round((opts.outWidth / ww));
        } else if (w <= h && h > hh) { //如果高度高的话根据宽度固定大小缩放
            be = Math.round((opts.outHeight / hh));
        }
        if (be <= 0) {
            be = 1;
        }
        return BitmapFactory.decodeFile(path, bitmapManage(be));
    }

    /**
     * 按比例压缩图片
     *
     * @param bitmap 需要压缩的源图片
     * @param ww     指定要压缩的图片宽度
     * @param hh     指定要压缩的图片高度
     * @return
     */
    public static Bitmap compBitmapByScale(Bitmap bitmap, float ww, float hh) throws Exception{

        if (bitmap == null) {
            throw new IllegalArgumentException("bitmap can not be empty.");
        }

        //设置默认缩放的高宽
        if (ww <= 0 || hh <= 0) {
            ww = 480;
            hh = 800;
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());

        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        //开始读入图片，此时把options.inJustDecodeBounds 设回true了
        newOpts.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(isBm, null, newOpts);
        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        //缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        int be = 1;//be=1表示不缩放
        if (w >= h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
            be = Math.round((newOpts.outWidth / ww));
        } else if (w <= h && h > hh) {//如果高度高的话根据宽度固定大小缩放
            be = Math.round((newOpts.outHeight / hh));
        }
        if (be <= 0)
            be = 1;

        newOpts.inPreferredConfig = Bitmap.Config.ARGB_8888;
        newOpts.inSampleSize = be;
        //重新读入图片，注意此时已经把options.inJustDecodeBounds 设回false了
        isBm = new ByteArrayInputStream(baos.toByteArray());
        Bitmap newBitmap = BitmapFactory.decodeStream(isBm, null, newOpts);

        closeInputStream(isBm);
        closeOutputStream(baos);
        return newBitmap;

    }


    private static void closeInputStream(InputStream in) {
        if (null != in) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void closeOutputStream(OutputStream out) {
        if (null != out) {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 按质量压缩图片
     *
     * @param src  需要被压缩的源图像
     * @param size 指定压缩的图片不超过该大小，单位KB
     * @return
     */
    public static ByteArrayOutputStream compBitmap(Bitmap src, int size) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        src.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;

        if (baos.toByteArray().length / 1024 > size) {
            while (baos.toByteArray().length / 1024 > size) {  //循环判断如果压缩后图片是否大于指定大小,大于继续压缩
                baos.reset();//重置baos即清空baos
                src.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options，把压缩后的数据存放到baos中
                options -= 10;//每次都减少10
            }
        }

        return baos;
    }

    /**
     * 按质量压缩图片
     *
     * @return
     */
    public static Bitmap compBitmapByQuality(Bitmap src, int size) {

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        src.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;

        if (baos.toByteArray().length / 1024 > size) {
            while (baos.toByteArray().length / 1024 > size) {  //循环判断如果压缩后图片是否大于指定大小,大于继续压缩
                baos.reset();//重置baos即清空baos
                src.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options，把压缩后的数据存放到baos中
                options -= 10;//每次都减少10
            }
        }

        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中

        return BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片;
    }

    /**
     * 把bitmap对象写入sdcard中
     *
     * @param bitmap
     * @param outFile
     */
    public static void writeToSdcard(Bitmap bitmap, File outFile) {
        //检测sdcard是否可用
        if (!CommonUtils.isSDCardMounted()) {
            throw new RuntimeException("sdcard is not available.");
        }
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(outFile);
            if (bitmap != null) {
                if (bitmap.compress(Bitmap.CompressFormat.PNG, 100,
                        fileOutputStream)) {
                    fileOutputStream.flush();
                }
            }
        } catch (IOException e) {
            outFile.delete();
            Log.e(TAG, e.getMessage(), e);
        } finally {
            if (null != bitmap) {
                bitmap.recycle();
            }
        }
    }
}
